import json
import os
import pickle
import time
from contextlib import suppress

import requests
from mutagen.mp3 import MP3

def print_introduction():
    # 打印华丽介绍
    print(r"""
    TechMouse Music Fetcher —— 您的音乐探索与下载新境界桥梁！

    **中文介绍：**
    欢迎来到TechMouse Music Fetcher，一款由技术鼠精心研发的音乐下载神器，旨在为您带来前所未有的音乐探索与下载体验。我们的目标是简化复杂的音乐获取过程，无论您身处何地，都能轻松触及心之所向的旋律。TechMouse Music Fetcher聚合全球海量音乐资源，一键下载，从经典老歌到流行新曲，满足您的所有音乐想象。我们坚持提供高清音质，保留音乐的每个细腻之处，让您沉浸在纯净的音乐享受中。此软件的二进制文件及源代码受法律保护，严禁任何形式的抄袭与非法传播，尊重原创，共创良好网络环境。

    **English Introduction:**
    Introducing TechMouse Music Fetcher — Your gateway to an elevated music exploration and downloading experience! Crafted by TechMouse, our software is designed to revolutionize how you discover and obtain music. Simplifying complex retrieval processes, we ensure that your favorite tunes are just a click away, anywhere, anytime. With access to a vast global music database, from timeless classics to the latest hits, TechMouse Music Fetcher caters to diverse tastes. We're committed to delivering high-quality audio, preserving every nuance of the original composition. Our binary files and source code are legally protected, and we strictly prohibit any form of plagiarism or unauthorized distribution. Let's uphold originality and foster a healthy digital ecosystem together.

    **版权声明：**
    TechMouse Music Fetcher及其所有相关二进制文件和源代码均为"技术鼠"原创作品，受国际版权法保护。未经授权，不得复制、修改或以任何形式传播本软件，违者将依法追责。尊重创新，维护正版，共建美好音乐未来。

    Contact:3238846019@qq.com | Website: https://engineerwin.online/
    """)
# 在程序运行时调用打印介绍函数


# 在这之后可以编写你的其他代码逻辑

music_save_path = 'music_save_path.pk1'
# 保存路径
def save_path(path):
    # 保存路径到文件
    with open(music_save_path, 'wb') as f:
        pickle.dump(path, f)
# 加载路径
def load_memory():
    # 从文件中加载路径
    if os.path.exists(music_save_path):
        with open(music_save_path, 'rb') as f:
            return pickle.load(f)
    return None

# 获取默认路径
def getdefault_path():
    # 获取默认路径
    return os.path.expanduser("~/Downloads")


# 判断音乐链接是否有效
def music_check(url):
    temp_dir = 'temp'
    temp_file_path = os.path.join(temp_dir, 'temp.mp3')

    # 确保临时目录存在
    if not os.path.exists(temp_dir):
        os.makedirs(temp_dir)

    try:
        # 下载音乐文件
        response = requests.get(url)
        response.raise_for_status()  # 这将抛出异常如果status_code不是200

        # 保存到临时文件
        with open(temp_file_path, 'wb') as f:
            f.write(response.content)

        # 检查音频文件
        audio = MP3(temp_file_path)
        duration = audio.info.length

        if duration > 0:
            print("The music file is valid.")
            return True
        else:
            print("The music file is invalid (duration <= 0).")
            return False

    except requests.RequestException as e:
        print(f"Network error occurred: {e}")
    except Exception as e:
        print(f"An error occurred: {e}")
    finally:
        # 清理：无论成功还是失败，尝试删除临时文件
        with suppress(Exception):  # 使用suppress忽略删除文件时可能产生的异常
            os.remove(temp_file_path)
    return False  # 如果发生错误，返回False



def handle_search_results(results):
    while True:
        action = input("请输入你想下载的歌曲序号（输入'q'返回搜索或'qq'退出程序）: ")
        if action.lower() == 'qq':
            print("程序已退出。")
            break
        elif action.lower() == 'q':
            return  # 返回上一层搜索
        else:
            try:
                choice = int(action)
                if 1 <= choice <= len(results):
                    item = results[choice - 1]
                    path = load_memory()
                    if path is None:
                        print('当前使用的默认路径为：', getdefault_path())
                    else:
                        print('上次使用的路径为：', path)
                    print('需要更新下载路径吗？y/n')
                    update = input()
                    if update.lower() == 'y':
                        path = input('请输入新的下载路径：')
                        save_path(path)  # 保存新路径
                    else:
                        path = getdefault_path() if path is None else path  # 使用上次路径或默认路径
                        print('已使用上次的路径。' if path is not None else '已使用默认路径。')
                    download(item['url_320'],
                             f"{item['title'].replace('/', '_')} by {item['author'].replace('/', '_')}", path)
                else:
                    print("无效的序号，请重新输入。")
            except ValueError:
                print("请输入有效的数字序号或'q'返回搜索，'qq'退出程序。")


def download(url, name,path):
    # 先检查下载的音乐是否有效
   if music_check(url):

       response = requests.get(url)
       if os.path.exists(path):  # 判断路径是否存放
           print('Invalid path')
       else:
           os.mkdir(path)
       with open(f'{path}//{name}.mp3', 'wb') as f:
           f.write(response.content)
       print(f'{name} download success !')
   else:
       print('The music link is no longer valid !')

def search_music(name):
    max_result = 20  # 最大搜索结果数
    count = 0  # 计数器
    search_results = []  # 创建空列表存储搜索结果
    for i in range(1, max_result+1):  # 循环至指定的最大页数
        time.sleep(0.6)
        data = {
            'input': name,
            'filter': 'name',
            f'page':{i} ,
            'type': 'netease',
        }

        try:
            response = requests.post('https://www.myfreemp3.com.cn/', cookies=cookies, headers=headers, data=data)
            response.raise_for_status()
            try:
                data = response.json()
                data_list = data.get('data', {}).get('list', [])
                if data_list:
                    for item in data_list:
                        authors = item.get('author', 'Unknown')
                        title = item.get('title', 'Unknown')
                        url_320 = item.get('url_320', 'No URL')
                        count += 1
                        print('\t')
                        print(f"\n{count}. {title} by {authors}")
                        search_results.append(item)  # 添加到结果列表
                        if count >= max_result:
                            break  # 获取到20条数据后停止
                    if count >= max_result:
                        break
                else:
                    print("No more songs to load.")
                    break
            except json.JSONDecodeError:
                print("Error decoding JSON response.")
                break
        except requests.RequestException as e:
            print(f"HTTP request failed: {e}")
            break

    return search_results  # 返回搜索结果列表


if __name__ == '__main__':
    # 请确保cookies和headers已经被正确赋值
    cookies = {
        'UM_distinctid': '18eb70018a83a5-0d5ec5d1aec5a9-4c657b58-146d15-18eb70018a9623',
        'CNZZDATA1281319036': '1166743205-1712467221-https%253A%252F%252Fcn.bing.com%252F%7C1717764720',
    }

    headers = {
        'accept': '*/*',
        'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6,ru;q=0.5',
        'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
        # 'cookie': 'UM_distinctid=18eb70018a83a5-0d5ec5d1aec5a9-4c657b58-146d15-18eb70018a9623; CNZZDATA1281319036=1166743205-1712467221-https%253A%252F%252Fcn.bing.com%252F%7C1717764720',
        'origin': 'https://www.myfreemp3.com.cn',
        'priority': 'u=1, i',
        'sec-ch-ua': '"Microsoft Edge";v="125", "Chromium";v="125", "Not.A/Brand";v="24"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"Windows"',
        'sec-fetch-dest': 'empty',
        'sec-fetch-mode': 'cors',
        'sec-fetch-site': 'same-origin',
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 Edg/125.0.0.0',
        'x-requested-with': 'XMLHttpRequest',
    }
    print_introduction()
    while True:
        music_name = input("请输入音乐名称（输入'q'退出程序）: ")
        if music_name.lower() == 'q':
            print("程序已退出。")
            break

        search_results = search_music(music_name)
        if not search_results:
            print("未找到相关音乐，请尝试其他关键词或稍后再试。")
            continue
        handle_search_results(search_results)



